package cn.mw.cmdb.controller;

import cn.mw.cmdb.entity.*;
import cn.mw.cmdb.enums.OperatorTypeDescEnum;
import cn.mw.cmdb.param.*;
import cn.mw.cmdb.service.ServiceAction;
import cn.mw.cmdb.service.impl.AssetsDiscoverServiceImpl;
import cn.mw.cmdb.service.impl.AssetsScanResultServiceImpl;
import cn.mw.cmdb.service.impl.CmdbServiceManage;
import cn.mw.cmdb.service.impl.MwCustomRuleServiceImpl;
import cn.mw.cmdb.timeplan.service.impl.MwTimePlanCommonImpl;
import cn.mw.cmdb.view.AssetsScanTotalResultConverter;
import cn.mw.cmdb.view.ViewConvertContext;
import cn.mw.cmdb.view.ViewManager;
import cn.mw.components.mongodb.page.MWPage;
import cn.mw.log.enums.BusinessLogType;
import cn.mw.log.enums.LogLevel;
import cn.mw.microMonitorCommon.api.common.BaseApiService;
import cn.mw.microMonitorCommon.api.common.ResponseBase;
import cn.mw.microMonitorCommon.api.user.MwUserApi;
import cn.mw.microMonitorCommon.constant.Constants;
import cn.mw.microMonitorCommon.entity.cmdb.TimePlanCommonDto;
import cn.mw.microMonitorCommon.operatorlog.client.MwLogClientSimple;
import cn.mw.microMonitorCommon.security.utils.SecurityUtils;
import cn.mw.microMonitorCommon.util.DateUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Collections;
import java.util.List;

import static cn.mw.cmdb.enums.PageDescEnum.AssetsDiscover;

@RequestMapping("/assetsDiscover")
@RestController
@Tag(name = "资产发现")
@Slf4j
public class AssetsDiscoverController extends BaseApiService {

    private final CmdbServiceManage cmdbServiceManage;

    private ViewManager viewManager;

    @Autowired
    private MwLogClientSimple logClientSimple;


    @Autowired
    private MwTimePlanCommonImpl mwTimePlanCommonImpl;

    @Autowired
    private MessageSource messageSource;

    @DubboReference(check = false, timeout = 100000, mock = "true")
    private MwUserApi mwUserApi;

    public AssetsDiscoverController(CmdbServiceManage cmdbServiceManage, ViewManager viewManager) {
        this.cmdbServiceManage = cmdbServiceManage;
        this.viewManager = viewManager;
    }

    @PostMapping("/createRule")
    @Operation(summary = "创建规则")
    public ResponseBase createRule(@RequestBody @Validated AssetsDiscoverInfo param) throws Exception {
        Object service = cmdbServiceManage.service(param, ServiceAction.add);

        String nickName = SecurityUtils.getUser().getNickName();
        logClientSimple.addBusinessLog(LogLevel.INFO.getId(), BusinessLogType.CMDB_MANAGE.getId(),
                messageSource.getMessage("mwCmdb-operation-log", new Object[]{nickName, DateUtils.now()
                        , BusinessLogType.CMDB_MANAGE.getCnName(), OperatorTypeDescEnum.add.getCname() + AssetsDiscover.getDesc(),
                        OperatorTypeDescEnum.add.getCname() + param.getRuleName(), Constants.OperationStatus.SUCCESS}, LocaleContextHolder.getLocale()));
        return setResultSuccess(service);
    }

    @PostMapping("/updateRule")
    @Operation(summary = "更新规则")
    public ResponseBase updateRule(@RequestBody @Validated AssetsDiscoverInfo param) throws Exception {
        Object service = cmdbServiceManage.service(param, ServiceAction.update);

        String nickName = SecurityUtils.getUser().getNickName();
        logClientSimple.addBusinessLog(LogLevel.INFO.getId(), BusinessLogType.CMDB_MANAGE.getId(),
                messageSource.getMessage("mwCmdb-operation-log", new Object[]{nickName, DateUtils.now()
                        , BusinessLogType.CMDB_MANAGE.getCnName(), OperatorTypeDescEnum.update.getCname() + AssetsDiscover.getDesc(),
                        OperatorTypeDescEnum.update.getCname() + param.getRuleName(), Constants.OperationStatus.SUCCESS}, LocaleContextHolder.getLocale()));
        return setResultSuccess(service);
    }

    @PostMapping("/deleteRule")
    @Operation(summary = "删除规则")
    public ResponseBase deleteRule(@RequestBody @Validated AssetsDiscoverIdsParam param) throws Exception {
        AssetsDiscoverServiceImpl modelService = (AssetsDiscoverServiceImpl) cmdbServiceManage.getModelService(AssetsDiscoverServiceImpl.ID);
        List<String> ruleNamesByIds = modelService.getRuleNamesByIds(param.getIds());
        String ruleNames = String.join(",", ruleNamesByIds);

        Object service = cmdbServiceManage.service(param, ServiceAction.batchRemove);

        String nickName = SecurityUtils.getUser().getNickName();
        logClientSimple.addBusinessLog(LogLevel.INFO.getId(), BusinessLogType.CMDB_MANAGE.getId(),
                messageSource.getMessage("mwCmdb-operation-log", new Object[]{nickName, DateUtils.now()
                        , BusinessLogType.CMDB_MANAGE.getCnName(), OperatorTypeDescEnum.remove.getCname() + AssetsDiscover.getDesc(),
                        OperatorTypeDescEnum.remove.getCname() + ": " + ruleNames, Constants.OperationStatus.SUCCESS}, LocaleContextHolder.getLocale()));
        return setResultSuccess(service);
    }

    @PostMapping("/pageList")
    @Operation(summary = "列表分页查询")
    public ResponseBase pageList(@RequestBody @Validated AssetsDiscoverSearchParam param) throws Exception {
        MWPage pageOld = param.getPage();
        MWPage page = new MWPage();
        page.setCurrent(pageOld.getCurrent());
        page.setSize(pageOld.getSize());
        List dataList = (List) cmdbServiceManage.service(param, ServiceAction.list);
        AssetsDiscoverServiceImpl modelService = (AssetsDiscoverServiceImpl) cmdbServiceManage.getModelService(AssetsDiscoverServiceImpl.ID);
        List ref = modelService.discoverInfoConvertDiscoverInfoVo(dataList, param);
        param.setPage(page);
        Object obj = viewManager.getListViewObject(ref, AssetsDiscoverInfo.class, param, null);
        return setResultSuccess(obj);
    }

    @PostMapping("/getRuleDetail")
    @Operation(summary = "获取规则列表-根据id数组")
    public ResponseBase getRuleDetail(@RequestBody AssetsDiscoverIdsParam param) throws Exception {
        AssetsDiscoverServiceImpl modelService = (AssetsDiscoverServiceImpl) cmdbServiceManage.getModelService(AssetsDiscoverServiceImpl.ID);
        List<AssetsDiscoverInfo> list = modelService.getRuleDetail(param);
        return setResultSuccess(list);
    }

    @PostMapping("/executorNow")
    @Operation(summary = "执行")
    public ResponseBase executorNow(@RequestBody @Validated InstanceRuleExecutorParam param) throws Exception {
        AssetsDiscoverServiceImpl modelService = (AssetsDiscoverServiceImpl) cmdbServiceManage.getModelService(AssetsDiscoverServiceImpl.ID);

        List<String> ruleNamesByIds = modelService.getRuleNamesByIds(param.getIds());
        String nickName = SecurityUtils.getUser().getNickName();
        Object ret = modelService.executorNow(param);
        logClientSimple.addBusinessLog(LogLevel.INFO.getId(), BusinessLogType.CMDB_MANAGE.getId(),
                messageSource.getMessage("mwCmdb-operation-log", new Object[]{nickName, DateUtils.now()
                        , BusinessLogType.CMDB_MANAGE.getCnName(), OperatorTypeDescEnum.scan.getCname() + AssetsDiscover.getDesc(),
                        OperatorTypeDescEnum.scan.getCname() + String.join(",", ruleNamesByIds), Constants.OperationStatus.SUCCESS}, LocaleContextHolder.getLocale()));
        return setResultSuccess(ret);
    }

    @PostMapping("/stopScan")
    @Operation(summary = "停止执行")
    public ResponseBase stopScan(@RequestBody @Validated InstanceRuleExecutorParam param) throws Exception {
        AssetsDiscoverServiceImpl modelService = (AssetsDiscoverServiceImpl) cmdbServiceManage.getModelService(AssetsDiscoverServiceImpl.ID);
        modelService.stopScan(param.getIds());
        return setResultSuccess();
    }

    @PostMapping("/batchAdd")
    @Operation(summary = "批量添加或者纳管")
    public ResponseBase batchAdd(@RequestBody ModelAddTangAssetsParam param) throws Exception {
        AssetsDiscoverServiceImpl modelService = (AssetsDiscoverServiceImpl) cmdbServiceManage.getModelService(AssetsDiscoverServiceImpl.ID);
        modelService.batchAdd(param);

        List<String> ruleNamesByIds = modelService.getRuleNamesByIds(Collections.singleton(param.getId()));
        String nickName = SecurityUtils.getUser().getNickName();
        logClientSimple.addBusinessLog(LogLevel.INFO.getId(), BusinessLogType.CMDB_MANAGE.getId(),
                messageSource.getMessage("mwCmdb-operation-log", new Object[]{nickName, DateUtils.now()
                        , BusinessLogType.CMDB_MANAGE.getCnName(), OperatorTypeDescEnum.batchAdd.getCname() + AssetsDiscover.getDesc(),
                        OperatorTypeDescEnum.batchAdd.getCname() + String.join(",", ruleNamesByIds), Constants.OperationStatus.SUCCESS}, LocaleContextHolder.getLocale()));

        return setResultSuccess();
    }

    @PostMapping("/getScanResult")
    @Operation(summary = "获取扫描信息")
    public ResponseBase<AssetsScanResultInfo> getScanResult(@RequestBody AssetsInstanceScanSearchParam param) throws Exception {
        AssetsScanResultServiceImpl service = (AssetsScanResultServiceImpl) cmdbServiceManage.getModelService(AssetsScanResultServiceImpl.ID);
        MWPage mwPage = param.getPage();
        //暂存当前页
        long current = mwPage.getCurrent();
        mwPage.setCurrent(1);
        List ret = service.getInsScanResultTest(param);
        ViewConvertContext context = new ViewConvertContext();
        context.put(ViewConvertContext.MwuserApiKey, mwUserApi);
        context.put(AssetsScanTotalResultConverter.SearchParamKey, param);

        //恢复当前页
        mwPage.setCurrent(current);
        Object obj = viewManager.getListViewObject(ret, AssetsScanTotalResultInfoVo.class, param, context);
        return setResultSuccess(obj);
    }

    @PostMapping("/getAssetsCountNumByRuleId")
    @Operation(summary = "统计每个扫描计划中的资产数量")
    public ResponseBase getAssetsCountNumByRuleId(@RequestBody AssetsInstanceScanSearchParam param) throws Exception {
        AssetsScanResultServiceImpl service = (AssetsScanResultServiceImpl) cmdbServiceManage.getModelService(AssetsScanResultServiceImpl.ID);
        ScanAssetsResultCountParam assetsCountNumByRuleId = service.getAssetsCountNumByRuleId(param.getId());
        return setResultSuccess(assetsCountNumByRuleId);
    }


    @PostMapping("/getAllNoManageAssetsInfos")
    @Operation(summary = "获取资产发现所有未纳管数据")
    public ResponseBase getAllNoManageAssetsInfos(@RequestBody AssetsScanNoManageSearchParam param) throws Exception {
        AssetsScanResultServiceImpl service = (AssetsScanResultServiceImpl) cmdbServiceManage.getModelService(AssetsScanResultServiceImpl.ID);
        List<ScanResultSuccessInfo> list = service.getAllNoManageAssetsInfos(param);
        Object obj = viewManager.getListViewObject(list, ScanResultSuccessInfo.class, param, null);
        return setResultSuccess(obj);
    }


//    @PostMapping("/getRuleScanResultTotal")
//    @Operation(summary = "获取扫描统计数据")
//    public ResponseBase getRuleScanResultTotal() throws Exception {
//        AssetsScanResultServiceImpl service = (AssetsScanResultServiceImpl) cmdbServiceManage.getModelService(AssetsScanResultServiceImpl.ID);
//        List<AssetsScanResultInfo> list = service.getRuleScanResultTotal();
//        return setResultSuccess(list);
//    }

    @PostMapping("/getFunctionModule")
    @Operation(summary = "获取功能模块")
    public ResponseBase functionModule() {
        return setResultSuccess(FunctionModuleEnum.getFunctionModule());
    }

    @PostMapping("/getProxyType")
    @Operation(summary = "获取代理类型")
    public ResponseBase getProxyType() {
        AssetsDiscoverServiceImpl assetsDiscoverService = (AssetsDiscoverServiceImpl) cmdbServiceManage.getModelService(AssetsDiscoverServiceImpl.ID);
        return setResultSuccess(assetsDiscoverService.getProxyType());
    }


    @PostMapping("/custom/createRule")
    @Operation(summary = "创建自定义规则")
    public ResponseBase createCustomRule(@RequestBody @Validated MwCustomRuleInfo param) throws Exception {
        Object service = cmdbServiceManage.service(param, ServiceAction.add);

        String nickName = SecurityUtils.getUser().getNickName();
        logClientSimple.addBusinessLog(LogLevel.INFO.getId(), BusinessLogType.CMDB_MANAGE.getId(),
                messageSource.getMessage("mwCmdb-operation-log", new Object[]{nickName, DateUtils.now()
                        , BusinessLogType.CMDB_MANAGE.getCnName(), OperatorTypeDescEnum.add.getCname() + AssetsDiscover.getDesc(),
                        OperatorTypeDescEnum.add.getCname() + param.getRuleName(), Constants.OperationStatus.SUCCESS}, LocaleContextHolder.getLocale()));
        return setResultSuccess(service);
    }

    @PostMapping("/custom/updateRule")
    @Operation(summary = "更新规则")
    public ResponseBase updateCustomRule(@RequestBody @Validated MwCustomRuleInfo param) throws Exception {
        Object service = cmdbServiceManage.service(param, ServiceAction.update);

        String nickName = SecurityUtils.getUser().getNickName();
        logClientSimple.addBusinessLog(LogLevel.INFO.getId(), BusinessLogType.CMDB_MANAGE.getId(),
                messageSource.getMessage("mwCmdb-operation-log", new Object[]{nickName, DateUtils.now()
                        , BusinessLogType.CMDB_MANAGE.getCnName(), OperatorTypeDescEnum.update.getCname() + AssetsDiscover.getDesc(),
                        OperatorTypeDescEnum.update.getCname() + param.getRuleName(), Constants.OperationStatus.SUCCESS}, LocaleContextHolder.getLocale()));
        return setResultSuccess(service);
    }

    @PostMapping("/custom/deleteRule")
    @Operation(summary = "删除规则")
    public ResponseBase deleteCustomRule(@RequestBody @Validated MwCustomRuleIdsParam param) throws Exception {
        MwCustomRuleServiceImpl modelService = (MwCustomRuleServiceImpl) cmdbServiceManage.getModelService(MwCustomRuleServiceImpl.ID);
        List<String> ruleNamesByIds = modelService.getRuleNamesByIds(param.getIds());
        String ruleNames = String.join(",", ruleNamesByIds);

        Object service = cmdbServiceManage.service(param, ServiceAction.batchRemove);

        String nickName = SecurityUtils.getUser().getNickName();
        logClientSimple.addBusinessLog(LogLevel.INFO.getId(), BusinessLogType.CMDB_MANAGE.getId(),
                messageSource.getMessage("mwCmdb-operation-log", new Object[]{nickName, DateUtils.now()
                        , BusinessLogType.CMDB_MANAGE.getCnName(), OperatorTypeDescEnum.remove.getCname() + AssetsDiscover.getDesc(),
                        OperatorTypeDescEnum.remove.getCname() + ": " + ruleNames, Constants.OperationStatus.SUCCESS}, LocaleContextHolder.getLocale()));
        return setResultSuccess(service);
    }

    @PostMapping("/custom/pageList")
    @Operation(summary = "列表分页查询")
    public ResponseBase pageCustomList(@RequestBody @Validated MwCustomRuleSearchParam param) throws Exception {
        List dataList = (List) cmdbServiceManage.service(param, ServiceAction.list);
        MwCustomRuleServiceImpl modelService = (MwCustomRuleServiceImpl) cmdbServiceManage.getModelService(MwCustomRuleServiceImpl.ID);
        List ref = modelService.dataListConvert(dataList);
        Object obj = viewManager.getListViewObject(ref, MwCustomRuleInfo.class, param, null);
        return setResultSuccess(obj);
    }

    @PostMapping("/getTimePlanInfos")
    @Operation(summary = "获取时间计划下拉信息")
    public ResponseBase<List<TimePlanCommonDto>> getTimePlanDropDown() throws Exception {
        List<TimePlanCommonDto> timePlanDropDown = mwTimePlanCommonImpl.getTimePlanDropDown();
        return setResultSuccess(timePlanDropDown);
    }

    @PostMapping("/createTimeTaskScanPlan")
    @Operation(summary = "创建定时任务资产发现计划")
    public ResponseBase createTimeTaskScanPlan(@RequestBody AssetsDiscoverInfo param) throws Exception {
        AssetsDiscoverServiceImpl modelService = (AssetsDiscoverServiceImpl) cmdbServiceManage.getModelService(AssetsDiscoverServiceImpl.ID);

        modelService.createTimeTaskScanPlan(param);
        return setResultSuccess();
    }

}
